package cn.zhuoqianmingyue.filter;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.concurrent.ConcurrentHashMap;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.http.HttpEntity;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.util.StringUtils;

import cn.hutool.json.JSONUtil;
import cn.zhuoqianmingyue.pojo.User;

public class SSOClientFilter implements Filter{
	private final String SUCESSURL = "/index/index";
	private final String SSOSERVERLOGINURL = "http://localhost:8080/ssoServer/login/login";
	private final String SSOSERVERAUTHENTICATIONURL = "http://localhost:8080/ssoServer/sso/authentication";
	public static ConcurrentHashMap<String,HttpSession> TICKET_SESSION_CACHE = new ConcurrentHashMap<String,HttpSession>();
	@Override
	public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
			FilterChain filterChain) throws IOException, ServletException {
		HttpServletRequest request = (HttpServletRequest )servletRequest;
		HttpServletResponse response = (HttpServletResponse )servletResponse;
		HttpSession session = request.getSession();
		String path = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath();
		String uri = request.getRequestURI();
		
		//被动单点退出
		String requestLogoutTicket = request.getParameter("requestLogout");
		if(!StringUtils.isEmpty(requestLogoutTicket)){
			ssoLogout(requestLogoutTicket);
			response.sendRedirect(SSOSERVERLOGINURL+"?service="+path);
			return;
		}
		//根据ticket获取用户信息
		String ticket = request.getParameter("ticket");
		if(!StringUtils.isEmpty(ticket)){
			User user = getUserByTicket(ticket);
			if(user == null){
				response.sendRedirect(SSOSERVERLOGINURL+"ERRORMSG="+"非法访问");
				return;
			}else{
				session.setAttribute("LOGIN_INFO", user);
				response.sendRedirect(path+SUCESSURL);
				TICKET_SESSION_CACHE.put(ticket, session);
				return;
			}
			
		}
		
		User user = (User)session.getAttribute("LOGIN_INFO");
		if(uri.endsWith("/login")){
			response.sendRedirect(SSOSERVERLOGINURL+"?service="+path);
			return;
		}
		if(null != user || uri.endsWith("css") || uri.endsWith("js")){
			filterChain.doFilter(servletRequest, servletResponse);
			return;
		}else{
			response.sendRedirect(SSOSERVERAUTHENTICATIONURL+"?service="+path);
			return;
		}
	}
	
	private void ssoLogout(String ticket) {
		if(TICKET_SESSION_CACHE.containsKey(ticket)){
			HttpSession sess = TICKET_SESSION_CACHE.get(ticket);
			if(null != sess){
				sess.invalidate();
			}
			TICKET_SESSION_CACHE.remove(ticket);
		}
	}
	private User getUserByTicket(String ticket)  {

		User user = null;
		CloseableHttpResponse closeableHttpResponse = null;
		try {
			CloseableHttpClient httpClient = HttpClients.createDefault();
			URI uriHttp = uriHttp = new URI("http://localhost:8080/ssoServer/sso/validateTicket");
			URIBuilder uriBuilder = new URIBuilder(uriHttp);
			uriBuilder.setParameter("ticket", ticket);
			URI uriParma  = uriBuilder.build();
			HttpGet httpGet = new HttpGet(uriParma);
			//执行请求访问
			closeableHttpResponse = httpClient.execute(httpGet);
			//获取返回HTTP状态码
			int satausCode = closeableHttpResponse.getStatusLine().getStatusCode();
			if(satausCode == 200 ){
				HttpEntity entity = closeableHttpResponse.getEntity();
				String content = EntityUtils.toString(entity,"UTF-8");
				user = JSONUtil.toBean(content, User.class);
				EntityUtils.consume(entity);
			}
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (URISyntaxException e) {
			e.printStackTrace();
		}finally{
			try {
				closeableHttpResponse.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return user;
	}
}
